import Router from 'koa-router';
import { SysRoleService } from '../../service/system/SysRole.js';
import {
  CreateSysRoleDto,
  UpdateSysRoleDto,
  SysRoleQueryDto,
} from '../../entities/system/SysRole.js';
import type { AppContext } from '../../types/index.js';
import { Response } from '../../utils/response.js';
import { BusinessException } from '../../types/exceptions.js';
import { ValidationUtil } from '../../utils/validation.js';

const router = new Router<Record<string, unknown>, AppContext>();

// 使用单例模式，避免重复创建服务实例
class RoleController {
  private static instance: RoleController;
  private readonly roleService: SysRoleService;

  private constructor() {
    this.roleService = new SysRoleService();
  }

  static getInstance(): RoleController {
    if (!RoleController.instance) {
      RoleController.instance = new RoleController();
    }
    return RoleController.instance;
  }

  /**
   * 创建角色
   * @description 创建新的系统角色
   */
  async create(ctx: AppContext): Promise<void> {
    const role = ctx.request.body as CreateSysRoleDto;

    // 参数验证
    ValidationUtil.validateRequiredString(role.role_name as string, '角色名');
    ValidationUtil.validateRequiredString(role.role_key as string, '角色唯一标识');

    // 检查角色Key是否已存在
    const existingRole = await this.roleService.loadRoleByKey(role.role_key as string);
    if (existingRole) {
      throw new BusinessException('角色标识已存在');
    }

    const roleId = await this.roleService.create(role);
    ctx.body = Response.success('创建成功', { id: roleId });
  }

  /**
   * 获取角色列表
   * @description 分页获取系统角色列表，支持多种查询条件
   */
  async list(ctx: AppContext): Promise<void> {
    const { page, pageSize, ...query } = ctx.query;
    const { pageNum, pageSizeNum } = ValidationUtil.validatePagination(
      page as string,
      pageSize as string
    );

    const result = await this.roleService.list(pageNum, pageSizeNum, query as SysRoleQueryDto);
    ctx.body = Response.pagination('查询成功', result);
  }

  /**
   * 更新角色信息
   * @description 根据ID更新角色信息
   */
  async update(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, '角色ID');
    const role = ctx.request.body as UpdateSysRoleDto;

    // 参数验证
    if (role.role_name) {
      ValidationUtil.validateRequiredString(role.role_name as string, '角色名');
    }

    if (role.role_key) {
      ValidationUtil.validateRequiredString(role.role_key as string, '角色唯一标识');

      // 检查角色Key是否已被其他角色使用
      const existingRole = await this.roleService.loadRoleByKey(role.role_key as string);
      if (existingRole && existingRole.id !== id) {
        throw new BusinessException('角色标识已存在');
      }
    }

    const success = await this.roleService.update(id, role);
    if (!success) {
      throw new BusinessException('角色不存在或已被删除');
    }

    ctx.body = Response.success('更新成功');
  }

  /**
   * 删除角色
   * @description 根据ID删除角色
   */
  async delete(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, '角色ID');

    // 检查是否为系统角色
    const role = await this.roleService.getById(id);
    if (role && role.is_sys === 1) {
      throw new BusinessException('系统角色不允许删除');
    }

    const success = await this.roleService.delete(id);
    if (!success) {
      throw new BusinessException('角色不存在');
    }

    ctx.body = Response.success('删除成功');
  }

  /**
   * 获取角色详情
   * @description 根据ID获取角色详情
   */
  async getById(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, '角色ID');

    const role = await this.roleService.getById(id);
    if (!role) {
      throw new BusinessException('角色不存在');
    }
    ctx.body = Response.success('获取成功', role);
  }

  /**
   * 获取指定类型的角色列表
   * @description 根据角色类型获取角色列表 (0:后台角色, 1:前台角色)
   */
  async getRolesByType(ctx: AppContext): Promise<void> {
    const type = parseInt(ctx.params.type as string, 10);
    if (isNaN(type) || (type !== 0 && type !== 1)) {
      throw new BusinessException('无效的角色类型');
    }

    const roles = await this.roleService.getRolesByType(type);
    ctx.body = Response.success('获取成功', roles);
  }
}

const controller = RoleController.getInstance();

// 路由定义 - 使用控制器方法
router.post('/create', (ctx: AppContext) => controller.create(ctx));
router.get('/list', (ctx: AppContext) => controller.list(ctx));
router.put('/:id', (ctx: AppContext) => controller.update(ctx));
router.delete('/:id', (ctx: AppContext) => controller.delete(ctx));
router.get('/:id', (ctx: AppContext) => controller.getById(ctx));
router.get('/by-type/:type', (ctx: AppContext) => controller.getRolesByType(ctx));

export default router;
